<template>
    <div class="video-container" @mouseenter="showControls = true" @mouseleave="startControlsTimer" v-loading="loading">
        <!-- @/assets/video/video.mp4 -->
        <video ref="videoPlayer" :src="props.videoInfo.video_url" @timeupdate="handleTimeUpdate" @click="togglePlay"></video>

        <!-- 自定义控制条 -->
        <div class="custom-controls" v-show="showControls">
            <!-- 后退10秒 -->
            <button @click="seekBackward">
                <el-icon><DArrowLeft /></el-icon>
            </button>
            <!-- 播放/暂停按钮 -->
            <button @click="togglePlay">
                <el-icon v-if="!isPlaying"><VideoPlay /></el-icon>
                <el-icon v-else><VideoPause /></el-icon>
            </button>
            <!-- 前进10秒 -->
            <button @click="seekForward">
                <el-icon><DArrowRight /></el-icon>
            </button>

            <!-- 进度条 -->
            <div class="progress-container">
                <span class="time">{{ formatTime(currentTime) }}</span>
                <el-slider v-model="sliderValue" :max="duration" :step="1" @change="handleSliderChange" @input="handleSliderInput" @mousedown="handleSliderInputStart" />
                <span class="time">{{ formatTime(duration) }}</span>
            </div>

            <!-- 音量控制 -->
            <div class="volume-control">
                <el-popover placement="top" trigger="hover" :teleported="false" width="auto" :show-arrow="false">
                    <template #reference>
                        <button @click="toggleMute">
                            <el-icon v-if="isMuted"><Mute /></el-icon>
                            <el-icon v-else><Microphone /></el-icon>
                        </button>
                    </template>
                    <el-slider v-model="volume" vertical height="80px" :step="0.1" :max="1" @change="handleVolumeChange" />
                </el-popover>
            </div>

            <!-- 全屏按钮 -->
            <button @click="toggleFullscreen">
                <el-icon><FullScreen /></el-icon>
            </button>
        </div>

        <div class="last-time" v-if="lastPlayedTime > 0">{{ $t('video_player.tip') }}{{ formatTime(lastPlayedTime) }}</div>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue'
import { useRoute } from 'vue-router'
import { useUserStore } from '@/stores/user'

import moment from 'moment'

import ResourceService from '@/api/resource'
import type { VideoInfo } from '@/types/resource'

const route = useRoute()
const userStore = useUserStore()
const courseId = computed(() => Number(route.params.courseId))
const unitId = computed(() => Number(route.params.unitId))
const props = defineProps<{
    videoInfo: VideoInfo
    videoId: number
}>()

const videoPlayer = ref<HTMLVideoElement | null>(null)
const currentTime = ref(0) // 记录视频当前播放的时间位置（秒）
const duration = ref(0) // 视频总时长（秒）
const sliderValue = ref(0) // 进度条滑块的值，与currentTime同步
const maxReachedTime = ref(0) // 记录用户观看到的最大时间位置（用于限制不能跳转到未观看部分）
const lastPlayedTime = ref(0) // 上次播放的时间位置
const isPlaying = ref(false) // 表示视频是否正在播放的状态
const isMuted = ref(false) // 表示视频是否静音的状态
const volume = ref(0.5) // 视频音量（0-1范围）
const showControls = ref(true) // 控制是否显示自定义控制条
const controlsTimer = ref<number | null>(null) // 存储控制条自动隐藏的定时器ID
const isDragging = ref(false) // 标记用户是否正在拖动进度条
const tempSliderValue = ref(0) // 在拖动进度条时临时存储滑块值
const loading = ref(true)
const hasRecordedStartTime = ref(false)
const allowFastForward = computed(() => props.videoInfo.allow_fast_forward === 1)

// 从本地存储加载上次播放时间
const loadLastPlayedTime = () => {
    const savedTime = Number(localStorage.getItem(`videoTime_${props.videoId}_${userStore.userinfoL?.id}`)) || props.videoInfo.progress?.last_position || 0 // 上次播放时间
    lastPlayedTime.value = savedTime
    maxReachedTime.value = lastPlayedTime.value
}

// 保存播放时间
const savePlayTime = (time: number) => {
    localStorage.setItem(`videoTime_${props.videoId}_${userStore.userinfoL?.id}`, time.toString())
}
// 保存进度条
const saveProgress = () => {
    if (currentTime.value === 0) return
    const startTime = localStorage.getItem(`videoTime_${props.videoId}_${userStore.userinfoL?.id}_start_time`) || moment().format('YYYY-MM-DD HH:mm:ss')
    const data = {
        student_id: userStore.userinfoL?.id || 0,
        position: Math.trunc(currentTime.value || 0),
        duration: Math.trunc(videoPlayer.value?.duration || 0),
        course_id: courseId.value,
        unit_id: unitId.value,
        start_time: startTime,
    }
    ResourceService.videoUpdate(props.videoId, data)
}

// 格式化时间为 MM:SS
const formatTime = (seconds: number) => {
    const mins = Math.floor(seconds / 60)
    const secs = Math.floor(seconds % 60)
    return `${mins}:${secs < 10 ? '0' : ''}${secs}`
}

// 播放/暂停切换
const togglePlay = () => {
    if (!videoPlayer.value) return

    if (videoPlayer.value.paused) {
        videoPlayer.value.play()
        isPlaying.value = true
        if (!hasRecordedStartTime.value) {
            saveProgress()
            localStorage.setItem(`videoTime_${props.videoId}_${userStore.userinfoL?.id}_start_time`, moment().format('YYYY-MM-DD HH:mm:ss'))
            hasRecordedStartTime.value = true
        }
    } else {
        videoPlayer.value.pause()
        isPlaying.value = false
    }

    // 重置控制条隐藏计时器
    startControlsTimer()
}

// 后退10秒
const seekBackward = () => {
    if (!videoPlayer.value) return

    const newTime = Math.max(0, videoPlayer.value.currentTime - 10)
    videoPlayer.value.currentTime = newTime
    startControlsTimer()
}

// 前进10秒
const seekForward = () => {
    if (!videoPlayer.value) return

    let newTime
    if (allowFastForward.value) {
        // 允许快进，不受最大观看时间限制
        newTime = Math.min(videoPlayer.value.duration || 0, videoPlayer.value.currentTime + 10)
    } else {
        // 不允许快进，限制在最大观看时间内
        newTime = Math.min(maxReachedTime.value, videoPlayer.value.currentTime + 10)
    }

    videoPlayer.value.currentTime = newTime
    startControlsTimer()
}

// 处理进度条拖动开始
const handleSliderInputStart = (value: number) => {
    isDragging.value = true
    tempSliderValue.value = sliderValue.value
}

// 处理进度条跳转
const handleSeek = (value: number) => {
    if (!videoPlayer.value) return

    // 确保不能跳转到超过最大观看时间
    // console.log(value, maxReachedTime.value)
    const seekTime = Math.min(value, maxReachedTime.value)
    videoPlayer.value.currentTime = seekTime
    startControlsTimer()
}

// 处理进度条拖动
const handleSliderInput = (value: number) => {
    if (!isDragging.value) return

    if (allowFastForward.value) {
        // 允许快进，只受视频总时长限制
        tempSliderValue.value = value
    } else {
        // 不允许快进，限制在最大观看时间内
        tempSliderValue.value = Math.min(value, maxReachedTime.value)
    }
}

// 处理进度条拖动结束
const handleSliderChange = (value: number) => {
    if (!videoPlayer.value) return

    let seekTime
    if (allowFastForward.value) {
        // 允许快进，不受最大观看时间限制
        seekTime = value
    } else {
        // 不允许快进，限制在最大观看时间内
        seekTime = Math.min(value, maxReachedTime.value)
    }

    videoPlayer.value.currentTime = seekTime
    sliderValue.value = seekTime
    currentTime.value = seekTime

    isDragging.value = false
    startControlsTimer()
}

// 处理时间更新
const handleTimeUpdate = () => {
    if (!videoPlayer.value || isDragging.value) return

    currentTime.value = videoPlayer.value.currentTime
    sliderValue.value = currentTime.value

    // 更新最大观看时间
    if (currentTime.value > maxReachedTime.value) {
        maxReachedTime.value = currentTime.value
        savePlayTime(maxReachedTime.value)
    }

    // 自动隐藏控制条
    if (isPlaying.value) {
        startControlsTimer()
    }
}

// 处理音量变化
const handleVolumeChange = (value: number) => {
    if (!videoPlayer.value) return

    videoPlayer.value.volume = value
    isMuted.value = value === 0
}

// 静音切换
const toggleMute = () => {
    if (!videoPlayer.value) return

    isMuted.value = !isMuted.value
    videoPlayer.value.muted = isMuted.value

    if (isMuted.value) {
        volume.value = 0
    } else {
        volume.value = 0.5
    }
    videoPlayer.value.volume = volume.value

    startControlsTimer()
}

// 全屏切换
const toggleFullscreen = () => {
    if (!videoPlayer.value) return

    const container = videoPlayer.value.parentElement
    if (!container) return

    if (!document.fullscreenElement) {
        container.requestFullscreen().catch(err => {
            console.error(`全屏错误: ${err.message}`)
        })
    } else {
        document.exitFullscreen()
    }

    startControlsTimer()
}

// 控制条自动隐藏计时器
const startControlsTimer = () => {
    if (controlsTimer.value) {
        clearTimeout(controlsTimer.value)
    }

    showControls.value = true
    controlsTimer.value = setTimeout(() => {
        if (isPlaying.value) {
            showControls.value = false
        }
    }, 3000)
}

// 初始化播放器
const initPlayer = () => {
    if (!videoPlayer.value) return

    loadLastPlayedTime()
    // 设置初始时间为上次观看时间
    if (lastPlayedTime.value > 0) videoPlayer.value.currentTime = lastPlayedTime.value

    // 设置初始音量
    videoPlayer.value.volume = volume.value

    // 监听视频加载元数据
    videoPlayer.value.addEventListener('loadedmetadata', () => {
        duration.value = videoPlayer.value?.duration || 0
    })

    // 加载完第一帧
    videoPlayer.value.addEventListener('canplay', () => {
        loading.value = false
    })

    // 监听播放结束
    videoPlayer.value.addEventListener('ended', () => {
        isPlaying.value = false
        saveProgress()
    })

    // 开始控制条隐藏计时
    startControlsTimer()
}

onMounted(() => {
    initPlayer()
})

// 当视频源变化时重置状态
watch(
    () => props.videoInfo.video_url,
    () => {
        initPlayer()
    },
)
</script>

<style lang="less" scoped>
.video-container {
    position: relative;
    padding: 1px;
    background-color: #000;

    &:hover {
        .custom-controls {
            opacity: 1;
        }
    }

    video {
        width: 100%;
        display: block;
        cursor: pointer;
    }

    .custom-controls {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;

        padding: 10px;
        background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
        opacity: 0;
        transition: opacity 0.3s;

        display: flex;
        align-items: center;
        gap: 10px;

        button {
            background: none;
            border: none;
            color: white;
            cursor: pointer;
            font-size: 18px;
            padding: 5px;
            border-radius: 4px;

            &:hover {
                background: rgba(255, 255, 255, 0.2);
            }
        }

        .progress-container {
            flex: 1;
            display: flex;
            align-items: center;
            gap: 10px;

            .time {
                color: white;
                font-size: 12px;
                min-width: 40px;
            }

            :deep(.el-slider) {
                flex: 1;

                .el-slider__runway {
                    background-color: rgba(255, 255, 255, 0.3);
                    height: 4px;
                }

                .el-slider__bar {
                    height: 4px;
                    background-color: #409eff;
                }

                .el-slider__button {
                    width: 12px;
                    height: 12px;
                    border: 2px solid #409eff;
                }
            }
        }

        .volume-control {
            position: relative;

            :deep(.el-popper) {
                box-shadow: none;
                border: none;
                padding: 0;
                min-width: auto;
                background-color: transparent;
            }

            :deep(.el-slider) {
                --el-slider-button-size: 10px;
                --el-slider-button-wrapper-size: 10px;
                --el-slider-button-wrapper-offset: -2px;

                .el-slider__button {
                    display: block;
                }
            }
        }
    }

    .last-time {
        position: absolute;
        top: 10px;
        left: 10px;

        border-radius: 4px;
        padding: 4px 8px;
        background: rgba(0, 0, 0, 0.5);
        color: white;
        font-size: 12px;
    }
}
</style>
